using System;
using SmartPeople.Framework.SecuritySpace;

namespace SmartPeople.Framework.SecuritySpace
{
    public class SecurityPermissions : ISecurityPermissions
    {
        public enum AccessState
        {
            Allow,
            Deny,
            Undefined
        }

        public int Count
        {
            get { return Provider.Count; }
        }

        private ISecurityPermissionsProvider provider;

        public SecurityPermissions(ISecurityPermissionsProvider provider)
        {
            this.provider = provider;
        }

        private ISecurityPermissionsProvider Provider
        {
            get { return provider; }
            set { provider = value; }
        }


        public ISecurityPermission DenyPermission(Guid roleID, Guid documentID)
        {
            return CreatePermission(roleID, documentID, BuiltInActions.FullControl, BuiltInStates.Any, AccessType.Deny);
        }

        public ISecurityPermission DenyPermission(Guid roleID, Guid documentID, Guid actionID)
        {
            return CreatePermission(roleID, documentID, actionID, BuiltInStates.Any, AccessType.Deny);
        }

        public ISecurityPermission DenyPermission(Guid roleID, Guid documentID, Guid actionID, Guid stateID)
        {
            return CreatePermission(roleID, documentID, actionID, stateID, AccessType.Deny);
        }


        public AccessType GetAccessType(Guid roleID, Guid documentID, Guid actionID, Guid stateID)
        {
            return Provider.GetAccessType(roleID, documentID, actionID, stateID);
        }

        public ISecurityPermission GetPermission(Guid roleID, Guid documentID, Guid actionID, Guid stateID)
        {
            return Provider.GetPermission(roleID, documentID, actionID, stateID);
        }

        #region CreatePermission

        public ISecurityPermission CreatePermission(Guid roleID, Guid documentID, AccessType accessType)
        {
            return CreatePermission(roleID, documentID, BuiltInActions.FullControl, accessType);
        }

        public ISecurityPermission CreatePermission(Guid roleID, Guid documentID, Guid actionId, AccessType accessType)
        {
            return CreatePermission(roleID, documentID, actionId, BuiltInStates.Any, accessType);
        }


        public ISecurityPermission CreatePermission(Guid roleID, Guid documentID,
                                                    Guid actionID, Guid stateID, AccessType accessType)
        {
            //TODO: fix the exception
            if (accessType == AccessType.Inherited)
                throw new ArgumentOutOfRangeException("Cannot create permission with ");

            return Provider.CreatePermission(roleID, documentID, actionID, stateID, accessType);
        }

        #endregion

        #region GrantPermission

        public ISecurityPermission GrantPermission(Guid roleID, Guid documentID)
        {
            return CreatePermission(roleID, documentID, AccessType.Allow);
        }

        public ISecurityPermission GrantPermission(Guid roleID, Guid documentID, Guid actionID)
        {
            return CreatePermission(roleID, documentID, actionID, AccessType.Allow);
        }

        public ISecurityPermission GrantPermission(Guid roleID, Guid documentID, Guid actionID, Guid stateID)
        {
            return CreatePermission(roleID, documentID, actionID, stateID, AccessType.Allow);
        }

        #endregion

        #region RevokePermission

        public void RevokePermission(Guid roleID, Guid documentID)
        {
            Provider.DeletePermission(roleID, documentID);
        }

        public void RevokePermission(Guid roleID, Guid documentID, Guid actionID)
        {
            Provider.DeletePermission(roleID, documentID, actionID);
        }

        public void RevokePermission(Guid roleID, Guid documentID, Guid actionID, Guid stateID)
        {
            Provider.DeletePermission(roleID, documentID, actionID, stateID);
        }

        #endregion

        public bool UpdatePermission(ISecurityPermission permission)
        {
            return Provider.UpdatePermission(permission);
        }

        public bool DeletePermission(Guid permissionID)
        {
            return Provider.DeletePermission(permissionID);
        }

        public bool DeletePermission(ISecurityPermission permission)
        {
            return Provider.DeletePermission(permission);
        }

        public bool DeletePermission(Guid roleID, Guid documentID, Guid actionID, Guid stateID)
        {
            return Provider.DeletePermission(roleID, documentID, actionID, stateID);
        }

        public bool DeletePermission(Guid roleID, Guid documentID, Guid actionID)
        {
            return Provider.DeletePermission(roleID, documentID, actionID);
        }

        public bool DeletePermission(Guid roleID, Guid documentID)
        {
            return Provider.DeletePermission(roleID, documentID);
        }

        #region GetPermissions

        public ISecurityPermission[] GetPermissions(Guid roleID, Guid documentID)
        {
            return Provider.GetPermissions(roleID, documentID);
        }

        #endregion

        #region IsGranted

        public bool IsGranted(Guid roleID, Guid documentID)
        {
            return IsGranted(roleID, documentID, BuiltInActions.Unknown, BuiltInStates.Unknown);
        }

        #endregion

        #region GetAccessState

        public AccessState GetAccessState(Guid roleID, Guid documentID, Guid actionID, Guid stateID)
        {
            ISecurityPermission[] securityPermissions = GetPermissions(roleID, documentID);
            AccessState accessState = AccessState.Undefined;

            foreach (ISecurityPermission securityPermission in securityPermissions)
            {
                if (
                    ((securityPermission.ActionID == BuiltInActions.FullControl) ||
                     (securityPermission.ActionID == actionID))
                    && (
                           (securityPermission.StateID == BuiltInStates.Any) ||
                           (securityPermission.StateID == stateID))
                    )
                {
                    if (securityPermission.AccessType == AccessType.Allow)
                        accessState = AccessState.Allow;

                    if (securityPermission.AccessType == AccessType.Deny)
                        return AccessState.Deny;
                }
            }
            return accessState;
        }

        #endregion

        #region IsGranted

        public bool IsGranted(Guid roleID, Guid documentID, Guid actionID, Guid stateID)
        {
            AccessState accessState = GetAccessState(roleID, documentID, actionID, stateID);
            return (AccessState.Allow == accessState);
        }

        #endregion

        #region IsAnyGranted

        public bool IsAnyGranted(Guid[] roleIDs, Guid documentID, Guid actionID, Guid stateID)
        {
            AccessState resultAccessState = AccessState.Undefined;
            foreach (Guid roleID in roleIDs)
            {
                AccessState accessState = GetAccessState(roleID, documentID, actionID, stateID);

                if (AccessState.Allow == accessState)
                    resultAccessState = AccessState.Allow;
                else
                    return false;
            }
            return (AccessState.Allow == resultAccessState);
        }

        #endregion

        #region Clear

        public void Clear()
        {
            Provider.Clear();
        }

        #endregion

        #region Old Methods to Remove

        //public ISecurityPermission GrantPermission(Guid roleID, Guid documentID)
        //{
        //    return GrantPermission(roleID, documentID, BuiltInActions.FullControl);
        //}

        //public ISecurityPermission GrantPermission(Guid roleID, Guid documentID, Guid actionID)
        //{
        //    return GrantPermission(roleID, documentID, actionID, BuiltInStates.Any);
        //}

        //public ISecurityPermission GrantPermission(Guid roleID, Guid documentID, Guid actionID, Guid stateID)
        //{
        //    // return CreatePermission(roleID, documentID, actionID, stateID, AccessType.Allow);
        //    throw new NotImplementedException();
        //}


        //public void RevokePermission(Guid roleID, Guid documentID)
        //{
        //    throw new NotImplementedException();
        //}

        //public void RevokePermission(Guid roleID, Guid documentID, Guid actionID)
        //{
        //    throw new NotImplementedException();
        //}


        //public bool RevokePermission(Guid roleID, Guid documentID, Guid actionID, Guid stateID)
        //{
        //    //return Provider.RevokePermission(roleID,documentID,actionID,stateID);
        //    throw new NotImplementedException();
        //} 

        #endregion
    }
}